package com.ronan.imserver.server;

import com.ronan.common.protocol.RIMProtocol;
import com.ronan.imserver.handler.RIMHandlerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;

/**
 * FileName    : com.ronan.imserver.server
 * Description :
 *
 * @author : ysk
 * @version : 1.0
 * Create Date : 2021/2/25 23:44
 **/
@Slf4j
@Component
public class RIMServer {

    /**
     * 1. 声明线程池
     */
    private final EventLoopGroup bossGroup = Epoll.isAvailable() ? new EpollEventLoopGroup(1) : new NioEventLoopGroup(1);
    private final EventLoopGroup workerGroup = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();

    @Value("${rim.server.port}")
    private int port;

    /**
     * 启动RIM服务
     *
     * @throws InterruptedException 中断异常
     */
    @PostConstruct
    public void start() throws InterruptedException {
        // 服务端引导器
        ServerBootstrap b = new ServerBootstrap();
        // 设置线程池
        b.group(bossGroup, workerGroup)
                // 设置ServerSocketChannel的类型
                .channel(Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                .localAddress(new InetSocketAddress(port))
                // 设置SocketChannel对应的Handler
                .childHandler(new RIMHandlerInitializer());

        //  服务器端监听客户端连接端口 绑定端口，阻塞等待直到完成
        ChannelFuture future = b.bind().sync();
        if (future.isSuccess()) {
            log.info("RIM Server start success!!");
        }
    }

    /**
     * 销毁服务
     */
    @PreDestroy
    public void destroy() {
        // 优雅地关闭两个线程池
        bossGroup.shutdownGracefully().syncUninterruptibly();
        workerGroup.shutdownGracefully().syncUninterruptibly();
        log.info("Shutdown RIM Server Success!");
    }

    /**
     * 消息推送
     *
     * @param protocol 协议数据包
     * @param channel  通道
     */
    public void sendMsg(RIMProtocol protocol, Channel channel) {
        log.info("[消息推送]==[{}]", protocol);
        channel.writeAndFlush(protocol);
    }
}
